package org.zw.android.framework.ioc;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;

/**
 * 注入核心工具类
 * 
 * @author zhouwei
 *
 */
public final class InjectCore {
	
	static final String TAG 						= "InjectCore" ;
	
	public static final int DEFAULT_INTEGER 		= 0 ;
	public static final String DEFAULT_STRING 		= "" ;
	
	private static Context 		mContext ;
	private static Resources	mResource ;
	
	private InjectCore(){
		
	}
	
	public static void initInjectCore(Context context){
		
		mContext	= context ;
		
		if(context != null){
			mResource 	= context.getResources() ;
		}
	}
	
	/**
	 * 针对普通的java 对象, 注入Android UI组件
	 * 
	 * @param obj
	 * @return
	 */
	public static View injectOriginalObject(Object obj){
		
		if(obj == null){
			return null ;
		}
		
		if(mContext == null){
			Log.e(TAG, "Error: The Context is null");
			return null;
		}
		
		Class<?> cls = obj.getClass() ;
		
		long enter = System.currentTimeMillis() ;
		
		try{
			
			InjectLayout layout = cls.getAnnotation(InjectLayout.class);
			int layoutRid 		= layout != null ? layout.layout() : DEFAULT_INTEGER ;
			
			if(layout == null || layoutRid == DEFAULT_INTEGER){
				Log.w(TAG, "Warring: The Object not layout resource");
				return null ;
			}
			
			View view = LayoutInflater.from(mContext).inflate(layoutRid, null);
			
			////////////////////字段注解///////////////////////
			Field[] fields = getDeclaredFields(cls);
			Object value = null ;

			for (Field f : fields) {

				// 可以访问
				f.setAccessible(true);

				// View注解类型
				InjectView injectview 	= f.getAnnotation(InjectView.class);
				int rid 				= injectview != null ? injectview.id() : 0 ;
				
				if (rid != DEFAULT_INTEGER) {
					value = view.findViewById(rid);
				}
				
				try {
					f.set(obj, value);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				
				if(value == null){
					continue ;
				}
				
				// add 事件
				addViewEvent(obj,f,injectview);
			}
			
			// set tag
			view.setTag(obj);
			
			Log.i(TAG, "Debug 在(" + cls.toString() + ")注解消耗时间 = " + (System.currentTimeMillis() - enter));
			
			// return
			return view ;
		} catch(Exception e){
			e.printStackTrace() ;
		}
		
		Log.i(TAG, "Debug 在(" + cls.toString() + ")注解消耗时间 = " + (System.currentTimeMillis() - enter));
		
		return null ;
	}
	
	/**
	 * 主动注入,参数: Activity,自定义View,Dialog,Fragment
	 * 
	 * @param obj
	 */
	public static void injectUIProperty(Object obj){
		
		if(obj == null){
			return ;
		}
		
		Class<?> cls = obj.getClass() ;
		
		long enter = System.currentTimeMillis() ;
		
		try{
			
			////////////////////类注解///////////////////////
			
			InjectLayout layout = cls.getAnnotation(InjectLayout.class);
			int layoutRid 		= layout != null ? layout.layout() : DEFAULT_INTEGER ;
			
			// Activity
			if(obj instanceof Activity){
				
				if(layout == null || layoutRid == DEFAULT_INTEGER){
					Log.w(TAG, "Warring: Activity not setContentView");
					return ;
				}
				
				// set Activity Content View
				((Activity)obj).setContentView(layoutRid);
			} 
			// ViewGroup
			else if(obj instanceof ViewGroup){
				
				ViewGroup root = (ViewGroup) obj ;
				
				// inflate layout
				if(layoutRid != DEFAULT_INTEGER){
					LayoutInflater.from(root.getContext()).inflate(layoutRid, root);
				}
			}
			
			////////////////////字段注解///////////////////////
			Field[] fields = getDeclaredFields(cls);

			for (Field f : fields) {

				// 可以访问
				f.setAccessible(true);

				// View注解类型
				InjectView injectview = f.getAnnotation(InjectView.class);
				if (injectview != null) {
					indectView(obj, f, injectview);
				}

				// 资源注解类型
				InjectResource injectint = f.getAnnotation(InjectResource.class);
				if(injectint != null){
					indectResource(obj, f, injectint);
				}
			}
		} catch(Exception e){
			e.printStackTrace() ;
		}
		
		Log.i(TAG, "Debug 在(" + cls.toString() + ")注解消耗时间 = " + (System.currentTimeMillis() - enter));
	}
	
	private static Field[] getDeclaredFields(Class<?> clazz) {

		List<Field> result = new ArrayList<Field>();

		Field[] fields = clazz.getDeclaredFields();

		for (Field field : fields) {
			
			if (Modifier.isFinal(field.getModifiers())) {
				continue;
			}
			
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}
			
			if ("serialVersionUID".equals(field.getName())) {
				continue;
			}
			
			result.add(field);
		}

		return result.toArray(new Field[0]);
	}
	
	private static void indectResource(Object obj,Field field,InjectResource inject){
		
		if(mResource == null){
			return ;
		}
		
		Object value = null ;
		
		if(inject.dimen() != DEFAULT_INTEGER){
			value	= mResource.getDimensionPixelSize(inject.dimen());
		} else if(inject.color() != DEFAULT_INTEGER){
			value	= mResource.getColor(inject.color());
		} else if(inject.string() != DEFAULT_INTEGER){
			value	= mResource.getString(inject.string());
		} else if(inject.stringArray() != DEFAULT_INTEGER){
			value	= mResource.getStringArray(inject.stringArray());
		} else if(inject.drawable() != DEFAULT_INTEGER){
			value	= mResource.getDrawable(inject.drawable());
		}
		
		try {
			field.set(obj, value);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	private static void indectView(Object obj,Field field,InjectView injectview){
		
		if(mContext == null){
			return ;
		}
		
		View view = null ;
		
		int layout 	= injectview.layout() ;
		int rid		= injectview.id() ;
		
		if(layout != DEFAULT_INTEGER){
			view	= LayoutInflater.from(mContext).inflate(layout, null);
		} else {
			
			if(rid != DEFAULT_INTEGER){
				
				// activity
				if(obj instanceof Activity){
					view = ((Activity)obj).findViewById(rid);
				} 
				// dialog
				else if(obj instanceof Dialog){
					view = ((Dialog)obj).findViewById(rid);
				} 
				// view
				else if(obj instanceof View){
					view = ((View)obj).findViewById(rid);
				} 
				// fragment
				else if(obj instanceof Fragment){
					view = ((Fragment)obj).getView().findViewById(rid);
				}
			} else {
				Log.e(TAG, "Error: Not support UI Component");
			}
		}
		
		try {
			field.set(obj, view);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		
		// view listener
		if(view == null){
			return ;
		}
		
		// add 事件
		addViewEvent(obj,field,injectview);
	}
	
	private static void addViewEvent(Object obj,Field field,InjectView injectview){
		
		// /////////////////////////View////////////////////////////////
		// onclick listener
		String onclick = injectview.onClick();
		if (onclick != null && !onclick.equals(DEFAULT_STRING)) {
			addViewOnClickListener(obj, field, onclick);
		}

		// onlongclick listener
		String onlongclick = injectview.onLongClick();
		if (onlongclick != null && !onlongclick.equals(DEFAULT_STRING)) {
			addViewOnLongClickListener(obj, field, onlongclick);
		}

		// ///////////////////////////AdapterView///////////////////////
		// on item click listener
		String onitemclick = injectview.onItemClickListener();
		if (onitemclick != null && !onitemclick.equals(DEFAULT_STRING)) {
			addAdapterViewOnItemClickListener(obj, field, onitemclick);
		}

		// on item click listener
		String onitemlongclick = injectview.onItemLongClickListener();
		if (onitemlongclick != null && !onitemlongclick.equals(DEFAULT_STRING)) {
			addAdapterViewOnItemLongClickListener(obj, field, onitemlongclick);
		}
	}
	
	// 单击事件
	private static void addViewOnClickListener(Object token, Field field,String clickMethod) {
		
		try {
			Object obj = field.get(token);
			
			if (obj instanceof View) {
				((View) obj).setOnClickListener(new ViewOnClickListener(token,clickMethod));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 长按事件
	private static void addViewOnLongClickListener(Object token, Field field,String clickMethod) {
		
		try {
			Object obj = field.get(token);
			
			if (obj instanceof View) {
				((View) obj).setOnLongClickListener(new ViewOnLongClickListener(token,clickMethod));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// AdapterView on item click
	@SuppressWarnings("rawtypes")
	private static void addAdapterViewOnItemClickListener(Object token, Field field,String clickMethod) {

		try {
			Object obj = field.get(token);

			if (obj instanceof View) {
				((AdapterView) obj).setOnItemClickListener(new ViewAdapterOnItemClick(token, clickMethod));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// AdapterView on item click
	@SuppressWarnings("rawtypes")
	private static void addAdapterViewOnItemLongClickListener(Object token,Field field, String clickMethod) {

		try {
			Object obj = field.get(token);

			if (obj instanceof View) {
				((AdapterView) obj).setOnItemLongClickListener(new ViewAdapterOnItemLongClick(token, clickMethod));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
